package com.jvyou.mybatis.builder.parser;

import com.jvyou.mybatis.exception.JvyouMybatisException;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 橘柚
 * @version 1.0-SNAPSHOT
 * @Date 2024/7/18 19:36
 * @Description xml配置文件解析器，单例模式
 */
public class XmlConfigParser {

    private static final XmlConfigContext context = XmlConfigContext.getInstance();

    private static final Map<String, XmlConfigNodeHandler> handlers;

    static {
        handlers = new HashMap<>();
        handlers.put("environment", new EnvironmentNodeHandler());
        handlers.put("plugins", new PluginsNodeHandler());
        handlers.put("mappers", new MappersNodeHandler());
        handlers.put("init", new InitNodeHandler());
    }

    @SuppressWarnings("unchecked")
    public static void parse(InputStream inputStream) {
        // XML 解析器
        SAXReader saxReader = new SAXReader();
        // 禁用 DTD 验证
        saxReader.setEntityResolver((publicId, systemId) -> new InputSource(new StringReader("")));
        Document document;
        try {
            document = saxReader.read(inputStream);
        } catch (DocumentException e) {
            throw new JvyouMybatisException("Unable to find the configuration file for Jvyou mybatis.");
        }
        List<Element> elements = document.getRootElement().elements();

        for (Element element : elements) {
            String elementName = element.getName().trim();
            if (handlers.containsKey(elementName)) {
                handlers.get(elementName).handle(element, context);
            } else {
                throw new JvyouMybatisException("The corresponding processor processing configuration node could not be found：" + elementName);
            }
        }
        // 关闭
        try {
            inputStream.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


}

